import 'dart:io';

import 'package:flutter/cupertino.dart';
import 'package:get/get.dart';
import 'package:jump_scape/js_config.dart';
import 'package:jump_scape/objectbox.g.dart';
import 'package:sign_in_with_apple/sign_in_with_apple.dart';

import 'js_box/js_init.dart';
import 'js_box/js_member.dart';
import 'js_game.dart';
import 'js_http/js_http.dart';

class JsLogin {
  void login({
    required bool isAppleLogin,
    required Function(MemberBox member) onSuccess,
    required Function(String msg) onFailed,
  }) async {
    String token;
    if (isAppleLogin) {
      try {
        final credential = await SignInWithApple.getAppleIDCredential(
          scopes: [
            AppleIDAuthorizationScopes.email,
            AppleIDAuthorizationScopes.fullName,
          ],
        );
        token = credential.identityToken ?? "";
      } catch (e) {
        e.printError();
        if (e is SignInWithAppleAuthorizationException) {
          if (AuthorizationErrorCode.canceled == e.code) {
            onFailed("");
          } else {
            onFailed(e.toString());
          }
        } else {
          onFailed(e.toString());
        }
        return;
      }
    } else {
      token = (await JsObjectBox.setting).deviceId;
    }

    final oauthType = isAppleLogin ? "3" : "4";

    final body = await JsHttp.post(JsApp.jsHttpLogin, false, {"oauthType": oauthType, "token": token});
    bool isSucc = body[1];
    if (isSucc) {
      Map<String, dynamic> map = body[2];

      final Map<String, dynamic> userInfo = map["userInfo"];

      final setting = await JsObjectBox.setting;
      setting.userToken = map["token"].toString(); // 用户登录令牌
      setting.userId = userInfo["userId"].toString(); // 用户ID
      JsObjectBox.settingBox.put(setting);
      debugPrint("[setting] ✅ $setting");

      if (token.isNotEmpty) {
        final memberOld = JsObjectBox.memberBox.query(MemberBox_.userId.equals(userInfo["userId"].toString())).build().findFirst();
        if (memberOld != null) {
          memberOld.userId = userInfo["userId"].toString(); // 用户ID
          memberOld.name = userInfo["nickname"].toString(); // 昵称
          memberOld.avatarUrl = userInfo["avatarUrl"].toString(); // 头像
          memberOld.balance = userInfo["availableCoins"].toString(); // 剩余金币个数
          memberOld.birth = DateTime.parse(userInfo["birthday"].toString()); // 生日 1995-01-01
          memberOld.country = userInfo["country"].toString(); // 国家
          JsObjectBox.memberBox.put(memberOld);

          debugPrint("[member] ✅ $memberOld");

          onSuccess(memberOld);
        } else {
          final memberNew = MemberBox.create(
            userId: userInfo["userId"].toString(), // 用户ID
            name: userInfo["nickname"].toString(), // 昵称
            avatarUrl: userInfo["avatarUrl"].toString(), // 头像
            balance: userInfo["availableCoins"].toString(), // 剩余金币个数
            birth: DateTime.parse(userInfo["birthday"].toString()), // 生日 1995-01-01
            country: userInfo["country"].toString(), // 国家
          );
          memberNew.id = JsObjectBox.memberBox.put(memberNew);

          debugPrint("[member] ✅ $memberNew");

          onSuccess(memberNew);
        }
      } else {
        onFailed("");
      }
    } else {
      onFailed(body[2]);
    }
  }

  Future<bool> isValidToken() async {
    final token = (await JsObjectBox.setting).userToken;
    if (token.isEmpty) return false;
    String code = (await JsHttp.post(JsApp.jsHttpIsValidToken, true, {"token": token}))[0];

    if (JsApp.jsCodeSuccess == code) {
      final userId = (await JsObjectBox.setting).userId;
      final body = await JsHttp.get(JsApp.jsHttpMember, {"userId": userId});
      code = body[0];

      switch (code) {
        case JsApp.jsCodeInvalidToken:
        case JsApp.jsCodeNoToken:
        case JsApp.jsCodeTokenError:
        case JsApp.jsCodeTokenHasExpired:
        case JsApp.jsCodeLoginOnOtherDevices:
          final setting = await JsObjectBox.setting;
          setting.userToken = '';
          setting.userId = '';
          JsObjectBox.settingBox.put(setting);

          debugPrint("[setting] ✅ $setting");

          return false;
      }
      return true;
    } else {
      final setting = await JsObjectBox.setting;
      setting.userToken = '';
      setting.userId = '';
      JsObjectBox.settingBox.put(setting);

      debugPrint("[setting] ✅ $setting");

      return false;
    }
  }

  Future<void> logout({
    required Function() onSuccess,
    required Function(String msg) onFailed,
  }) async {
    final body = await JsHttp.post(JsApp.jsHttpLogout, false);
    bool isSucc = body[1];
    if (isSucc) {
      final setting = await JsObjectBox.setting;
      setting.userToken = '';
      setting.userId = '';
      JsObjectBox.settingBox.put(setting);

      debugPrint("[setting] ✅ $setting");

      onSuccess();
    } else {
      onFailed(body[2]);
    }
  }

  Future<void> deleteAccount({
    required Function() onSuccess,
    required Function(String msg) onFailed,
  }) async {
    final body = await JsHttp.post(JsApp.jsHttpDeleteAccount, false);
    bool isSucc = body[1];
    if (isSucc) {
      final setting = await JsObjectBox.setting;

      var memberOld = JsObjectBox.memberBox.query(MemberBox_.userId.equals(setting.userId)).build().findFirst();
      if (memberOld != null) JsObjectBox.memberBox.remove(memberOld.id);

      try {
        final audioFile = File((await memberOld?.audioPathReal()) ?? '');
        if (audioFile.existsSync()) {
          audioFile.deleteSync();
        }
      } catch (e) {}

      JsGame().deleteByUserId(userId: setting.userId);

      setting.userToken = '';
      setting.userId = '';
      JsObjectBox.settingBox.put(setting);

      debugPrint("[setting] ✅ $setting");
      debugPrint("[member] ✅ $memberOld");

      onSuccess();
    } else {
      onFailed(body[2]);
    }
  }
}
